package design.pattern.Lu23BridgePattern;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

/**
 * @program JavaBase
 * @description: 桥接模式 - 聚合支付平台：多渠道多方式支付
 *  - 将抽象(支付渠道)与实现(密码支付、人脸支付、指纹支付)分离
 *  - 把多种可匹配的整合
 *  - 即，核心实现：A类(支付渠道)中含有B类(支付方式)的接口，在A类中通过构造函数等方式传递B类，这里B类就是与A产生关联设计的桥
 *  - 支付渠道(2) * 支付方式(3) = 最终实现
 *  - 拓展：1个渠道，只需拓展一个支付渠道即可；拓展1个支付方式，只需拓展一个即可，而不用拓展很多，体现出结构的灵活
 * @author: zhanglu
 * @create: 2022-05-17 10:35:00
 */
@Slf4j
public class BridgePattern03 {

    /*****************支付渠道*****************/
    static abstract class Pay{
        protected IPayMode payMode;
        public Pay(IPayMode payMode){
            this.payMode = payMode;
        }
        abstract String transfer(String data);
    }

    //微信支付
    @Slf4j
    static class WxPay extends Pay{

        public WxPay(IPayModeAbstract payMode) {
            super(payMode);
        }

        @Override
        String transfer(String data) {
            log.info("模拟微信渠道支付划账开始");
            Object res = payMode.execute(data);
            log.info("模拟微信渠道支付划账成功，{}", res.toString());
            return res.toString();
        }
    }

    //微信支付
    @Slf4j
    static class AliPay extends Pay{

        public AliPay(IPayModeAbstract payMode) {
            super(payMode);
        }

        @Override
        String transfer(String data) {
            log.info("模拟支付宝渠道支付划账开始");
            Object res = payMode.execute(data);
            log.info("模拟支付宝渠道支付划账成功，{}", res.toString());
            return res.toString();
        }
    }

    /*****************支付方式*****************/
    //支付模式统一接口定义：整个支付过程需要经过的步骤
    interface IPayMode{
        Object execute(String data);
    }

    //支付模式模版方法
    static abstract class IPayModeAbstract implements IPayMode{
        abstract boolean security(String data);
        abstract Object handler(String data);
        abstract Object postHandler(String data);
        protected Object templateMethod(String data){
            if(!security(data)){
               return null;
            }
            Object res = handler(data);
            return postHandler(res.toString());
        }
    }

    //密码支付
    @Slf4j
    static class PayCypher extends IPayModeAbstract{

        @Override
        public boolean security(String data) {
            log.info("密码支付，风控校验环境安全");
            return true;
        }

        @Override
        public Object handler(String data) {
            log.info("密码支付，第三方接口调用");
            return "ok";
        }

        @Override
        public Object postHandler(String data) {
            log.info("密码支付，接口返回处理，统一封装");
            return "ok";
        }

        @Override
        public Object execute(String data) {
            log.info("密码支付，执行");
            return templateMethod(data);
        }

    }

    //人脸支付
    @Slf4j
    static class PayFaceMode extends IPayModeAbstract{

        @Override
        public boolean security(String data) {
            log.info("人脸支付，风控校验环境安全");
            return true;
        }

        @Override
        public Object handler(String data) {
            log.info("人脸支付，第三方接口调用");
            return "ok";
        }

        @Override
        public Object postHandler(String data) {
            log.info("人脸支付，接口返回处理，统一封装");
            return "ok";
        }

        @Override
        public Object execute(String data) {
            log.info("人脸支付，执行");
            return templateMethod(data);
        }

    }

    //指纹支付
    @Slf4j
    static class PayFingerprintMode extends IPayModeAbstract{

        @Override
        public boolean security(String data) {
            log.info("指纹支付，风控校验环境安全");
            return true;
        }

        @Override
        public Object handler(String data) {
            log.info("指纹支付，第三方接口调用");
            return "ok";
        }

        @Override
        public Object postHandler(String data) {
            log.info("指纹支付，接口返回处理，统一封装");
            return "ok";
        }

        @Override
        public Object execute(String data) {
            log.info("指纹支付，执行");
            return templateMethod(data);
        }

    }

    /*****************测试*****************/

    @Test
    public void test01(){
        WxPay wxPay = new WxPay(new PayFaceMode());
        wxPay.transfer("111");

        log.info("------------------------");

        AliPay aliPay = new AliPay(new PayFingerprintMode());
        aliPay.transfer("222");
    }

}
